#include "videoplugin.h"
#include <QtGui>
#include <Maestro/mcplugins.h>
#include <algorithm> // for random_shuffle
#include <ctime> // time used as random seed
using namespace std; // namespace for algorithms

VideoPlugin::VideoPlugin()
{
    srand((time(NULL)));
    player=new Phonon::VideoWidget();
    player->setMouseTracking(true);
    mediaObject=new Phonon::MediaObject();
    audioOutput =new Phonon::AudioOutput(Phonon::VideoCategory, this);
    Phonon::createPath(mediaObject,audioOutput); // connect the two nodes so that the media object can send the sound to the audio output
   // connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish())); // connect signal from media object
    connect(mediaObject, SIGNAL(finished()), this, SLOT(finished()));
    connect(mediaObject,SIGNAL(metaDataChanged()),this,SLOT(dataChanged()));
    acceleratedMute=false;
    ffTimer = new QTimer(this);
    connect(ffTimer,SIGNAL(timeout()),this,SLOT(ff()));
    Phonon::createPath(mediaObject,player);
    rwTimer = new QTimer(this);
    connect(rwTimer,SIGNAL(timeout()),this,SLOT(rw()));
    connect(mediaObject,SIGNAL(stateChanged(Phonon::State,Phonon::State)),this,SLOT(stateChange(Phonon::State,Phonon::State)));
    connect(mediaObject,SIGNAL(currentSourceChanged(Phonon::MediaSource)),this,SLOT(mediaSourceChanged(Phonon::MediaSource)));
}

QString VideoPlugin::getName() {
    return "Video";
}

void VideoPlugin::test() {

}

QIcon VideoPlugin::getImage() {
    return QIcon(":/imgs/3F00_videosButton2.png");
}

QIcon VideoPlugin::getIcon(MediaFile * mediaFile) {
    return QIcon(":/imgs/videos.png");
}

QStringList VideoPlugin::getExtensions() {
    QStringList list=QStringList();
    list.append("avi");
    list.append("mp4");
    return list;
}

QWidget * VideoPlugin::getInterface() {
    return player;
}

void VideoPlugin::setMediaFile(MediaFile * mediaFile) {

    mediaObject->setCurrentSource(mediaFile->fileLocation+"/"+mediaFile->shortName);
    Phonon::createPath(mediaObject,player);
    mediaObject->play();
    qDebug() <<"video should be playing now";
}

void VideoPlugin::setMediaQueue(QList<MediaFile *> * files, int start) {
    if(index==start&&files==this->files) {
        return;
    }
    this->files=files;
    ffTimer->stop();
    rwTimer->stop();
    acceleratedMute=false;
    mediaObject->queue().clear();
    queue.clear();
    tmpQueue.clear();
    foreach(MediaFile * file, *files) { // append each file to queue
        Phonon::MediaSource source(file->fileLocation+"/"+file->shortName);
        queue.append(source);
        tmpQueue.append(source); // keep a copy for restoration purposes
    }
    mediaObject->setCurrentSource(queue.at(start).fileName()); // set the sources to play when the current source has finished
    index=start;
    mediaObject->play();
    emit stateChanged(true);
    emit fileChanged(queue.at(start).fileName(),start,queue.size());
    setShuffleState(shuffle);
}

void VideoPlugin::dataChanged() {
    //qDebug() <<"state changed "<<newS<<" "<<oldS;
    qDebug()<<mediaObject->metaData();
}

void VideoPlugin::play() {
    if(acceleratedMute) {
        audioOutput->setMuted(false);
        acceleratedMute=false;
    }
    ffTimer->stop();
    rwTimer->stop();
    if(mediaObject->state()==Phonon::PausedState||mediaObject->state()==Phonon::StoppedState) {
        mediaObject->play();
        emit stateChanged(true);
    } else {
        mediaObject->pause();
        emit stateChanged(false);
    }
}

void VideoPlugin::fastForward() {
    if(!audioOutput->isMuted()) {
       acceleratedMute=true;
       audioOutput->setMuted(true);
    }
    mediaObject->pause();
    emit stateChanged(false);
    rwTimer->stop();
    ffTimer->start(100);

}

void VideoPlugin::ff() {
    if (mediaObject->remainingTime()>0){
         mediaObject->seek(mediaObject->currentTime()+1000); // 1 second
     } else {
         mediaObject->stop();
         if(acceleratedMute) {
             audioOutput->setMuted(false);
             acceleratedMute=false;
         }
     }
}

void VideoPlugin::rewind() {
    if(!audioOutput->isMuted()) {
       acceleratedMute=true;
       audioOutput->setMuted(true);
    }
    mediaObject->pause();
    emit stateChanged(false);
    ffTimer->stop();
    rwTimer->start(100);
}

void VideoPlugin::rw() {

    if (mediaObject->currentTime()>0){
        if(mediaObject->currentTime()-1000<=0) {
            rwTimer->stop();
            if(acceleratedMute) {
                audioOutput->setMuted(false);
                acceleratedMute=false;
            }
        }
        mediaObject->seek(mediaObject->currentTime()-1000); // 1 second
        
     } else {
         rwTimer->stop();
         if(acceleratedMute) {
             audioOutput->setMuted(false);
             acceleratedMute=false;
         }
     }
}

void VideoPlugin::stop() {
    if(acceleratedMute) {
        audioOutput->setMuted(false);
    }
    ffTimer->stop();
    rwTimer->stop();
    mediaObject->stop();
    emit stateChanged(false);
}

void VideoPlugin::setVolume(int volume) {
    audioOutput->setVolume(volume/100.0);
}

void VideoPlugin::finished() { // signal when the last item in the queue has finished playing
    if(repeat == 2) // repeat one
    {
        mediaObject->stop();
        mediaObject->play();
    }
    else if(index+1<queue.size()) // go to the next video
    {
        index++;
        mediaObject->setCurrentSource(queue.at(index).fileName());
        mediaObject->play();
        qDebug() <<"Now playing: "<<queue.at(index).fileName();
        emit stateChanged(true);
    }
    else if(index == queue.size()-1 && repeat == 1) // repeat all -- go to first video
    {
        index = 0;
        mediaObject->stop();
        mediaObject->setCurrentSource(queue.at(index).fileName());
        mediaObject->play();
        qDebug() <<"Now playing: "<<queue.at(index).fileName();
        emit stateChanged(true);
    }
    else // (index == queue.size()-1) // repeat off & end of queue
    {
        index = 0;
        mediaObject->stop();
        mediaObject->setCurrentSource(queue.at(index).fileName());
        emit stateChanged(false);
    }
}

void VideoPlugin::aboutToFinish()
{

}

bool VideoPlugin::isPlaying() {
    if(!ffTimer->isActive()&&!rwTimer->isActive()&&mediaObject->state()==Phonon::PlayingState) {
        return true;
    }

    return false;
}

void VideoPlugin::next() {
    if(repeat == 2) // repeat one
    {
        // do nothing -- stay on the same video
    }
    else if(index+1<queue.size()) // go to the next video
    {
        index++;
        mediaObject->setCurrentSource(queue.at(index).fileName());
        mediaObject->play();
        qDebug() <<"Now playing: "<<queue.at(index).fileName();
        emit stateChanged(true);
        emit fileChanged(mediaObject->currentSource().fileName(), index, queue.size());
    }
    else if(index == queue.size()-1 && repeat == 1) // repeat all -- go to first video
    {
        index = 0;
        mediaObject->setCurrentSource(queue.at(index).fileName());
        mediaObject->play();
        qDebug() <<"Now playing: "<<queue.at(index).fileName();
        emit stateChanged(true);
    }
}

void VideoPlugin::previous() {
    if(repeat == 2) // repeat one
    {
        // do nothing -- stay on the same video
    }
    else if(index>0)
    {
        index--;
        mediaObject->setCurrentSource(queue.at(index).fileName());
        mediaObject->play();
        qDebug() <<"Now playing: "<<queue.at(index).fileName();
        emit stateChanged(true);
        emit fileChanged(mediaObject->currentSource().fileName(), index, queue.size());
    }
    else if(index == 0 && repeat == 1) // repeat all -- go to last video
    {
        index = queue.size()-1;
        mediaObject->setCurrentSource(queue.at(index).fileName());
        mediaObject->play();
        qDebug() <<"Now playing: "<<queue.at(index).fileName();
        emit stateChanged(true);
    }
}

bool VideoPlugin::setSlider(Phonon::SeekSlider *slider) {
    slider->setMediaObject(mediaObject);

    return true;
}

void VideoPlugin::stateChange(Phonon::State newS, Phonon::State oldS) {
    if(newS==Phonon::ErrorState) {
        emit error("Error. The file could not be played");
        mediaObject->stop();
        emit stateChanged(false);
    }
}

void VideoPlugin::mediaSourceChanged(Phonon::MediaSource source) {
    emit fileChanged(source.fileName(),queue.indexOf(source),queue.size());
}

void VideoPlugin::setShuffleState(bool shuffleState){
    this->shuffle=shuffleState;
    qDebug()<<"shuffle = " << shuffle;
    if(queue.isEmpty()) return; // shuffle has been clicked before the queue has been set. set the queue first
    if(shuffle) // shuffle the queue
    {
        while(queue.operator ==(tmpQueue)) // ensure that you don't shuffle to the original queue
            random_shuffle(queue.begin(), queue.end());
        qDebug()<<"Queue is shuffled";
        for(int i = 0; i < queue.size(); i++)
                qDebug()<<queue.at(i).fileName();
    }
    else // sort the queue with help from the temp queue
    {
        for(int i = 0; i < queue.size(); ++i)
            queue.replace(i, tmpQueue[i]);
        qDebug()<<"Queue is sorted";
    }
}

void VideoPlugin::setRepeatState(int repeatState){
    this->repeat=repeatState;
    qDebug() << "repeat = " << repeat << " (0 = off, 1 = all, 2 = one)";
}

Q_EXPORT_PLUGIN2(bmc_videoplugin, VideoPlugin)
